package com.marklogic.ps.servicetester.services;

import java.io.IOException;

import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.log4j.Logger;

import com.marklogic.ps.servicetester.domain.Query;
import com.marklogic.ps.servicetester.domain.ServerConnectionInfo;


public class ServiceHelper {
	
	protected final static Logger logger = Logger.getLogger(ServiceHelper.class);
	
	// This should be the complete http url the the .xqy service
	//private String url;
	
	// This is the name of the user collection, NOTE this collection must already exist in MarkLogic
	private String collectionName = "Foo";
	
	// Hard coded sample request document.  NOTE this differs slightly from
	// the XCC example, as this request contains an outer wrapper and
	// the service parameters expressed in the XML request
	private final static String servicesRequest = 
		"<request><list/></request>";
	
	//private String httpUsername = "admin";
	//private String httpPassword = "ML1234";
	//private String httpPassword = "admin";
	
	private ServerConnectionInfo sci;
	
	public ServiceHelper(ServerConnectionInfo info) {
		this.sci = info;
	}
	
	public String getServices() throws HttpException, IOException {
		HttpClient httpClient = getHttpClient();
        PostMethod method = new PostMethod(sci.getBaseUrl() + "service-tester/service-list.xqy");

        NameValuePair requestPair = new NameValuePair("request", servicesRequest);
        method.setRequestBody(new NameValuePair[]{requestPair});

        int response = httpClient.executeMethod(method);
        
        if (response != 200) {
        	throw new IOException("Service execution failed: " 
        			+ response + ", uri=" + method.getURI() + "\n" + method.getResponseBodyAsString());
        }
        String responseBody = method.getResponseBodyAsString();
        return responseBody;
	}
	
	public String runQuery(Query query, String queryText) throws HttpException, IOException {
		if (logger.isDebugEnabled()) {
			logger.debug("Running query: " + query);
			logger.debug(queryText);
		}
		HttpClient httpClient = getHttpClient();
		PostMethod method = new PostMethod(sci.getBaseUrl() + query.getService().getXqueryPath());
		
		// TODO make this configurable to send the request as body or as namevaluepairs
		method.setRequestEntity(new StringRequestEntity(queryText));
		method.setRequestHeader("Content-type", "text/xml; charset=UTF-8");
		
		//NameValuePair requestPair = new NameValuePair("request", queryText);
        //method.setRequestBody(new NameValuePair[]{requestPair});

        int response = httpClient.executeMethod(method);
        String responseBody = method.getResponseBodyAsString();
        if (logger.isDebugEnabled()) {
			logger.debug("Response: " + responseBody);
		}
        return responseBody;
	}
	
	private HttpClient getHttpClient() {
		HttpClient httpClient = new HttpClient();

        HttpClientParams params = httpClient.getParams();
        params.setHttpElementCharset("UTF-8");
        params.setContentCharset("UTF-8");

        //httpClient.getHostConfiguration().setProxy("my.proxyhost.com", 80);
        Credentials defaultcreds = new UsernamePasswordCredentials(sci.getUsername(), sci.getPassword());
        httpClient.getState().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM), defaultcreds);
        return httpClient;
	}

}
